/**
 * 通用工具类库
 * 提供常用的数据处理、格式化、验证等功能
 * 用于提高代码复用性和开发效率
 * 
 * 作者：AI语言学习应用开发团队
 * 创建时间：2024年
 * 更新时间：2024年
 * 
 * 主要功能模块：
 * - ValidationUtils：数据验证工具类，提供各种数据类型验证
 * - NumberUtils：数字格式化工具类，处理数字显示和格式化
 * - DateUtils：日期时间工具类，处理日期格式化和时间计算
 * - StringUtils：字符串处理工具类，提供字符串操作方法
 * - ArrayUtils：数组处理工具类，提供数组操作和处理方法
 * - ObjectUtils：对象处理工具类，提供对象操作和深拷贝等
 * - ErrorUtils：错误处理工具类，统一错误处理和日志记录
 * - PerformanceUtils：性能监控工具类，提供性能测试和优化方法
 */

/**
 * 数据验证工具类
 * 提供各种数据验证功能
 */
export class ValidationUtils {
  /**
   * 验证是否为空值
   * @param {any} value - 要验证的值
   * @returns {boolean} 是否为空
   */
  static isEmpty(value) {
    return value === null || value === undefined || value === '' || 
           (Array.isArray(value) && value.length === 0) ||
           (typeof value === 'object' && Object.keys(value).length === 0);
  }

  /**
   * 验证是否为有效的数字
   * @param {any} value - 要验证的值
   * @returns {boolean} 是否为有效数字
   */
  static isValidNumber(value) {
    return !isNaN(value) && isFinite(value) && value !== null && value !== '';
  }

  /**
   * 验证是否为有效的整数
   * @param {any} value - 要验证的值
   * @param {number} min - 最小值（可选）
   * @param {number} max - 最大值（可选）
   * @returns {boolean} 是否为有效整数
   */
  static isValidInteger(value, min = null, max = null) {
    if (!this.isValidNumber(value)) return false;
    const num = parseInt(value, 10);
    if (num !== parseFloat(value)) return false;
    if (min !== null && num < min) return false;
    if (max !== null && num > max) return false;
    return true;
  }

  /**
   * 验证是否为有效的分数（0-100）
   * @param {any} value - 要验证的值
   * @returns {boolean} 是否为有效分数
   */
  static isValidScore(value) {
    return this.isValidNumber(value) && value >= 0 && value <= 100;
  }

  /**
   * 验证是否为有效的课程ID
   * @param {any} value - 要验证的值
   * @returns {boolean} 是否为有效课程ID
   */
  static isValidLessonId(value) {
    return this.isValidInteger(value, 1);
  }

  /**
   * 验证是否为有效的经验值
   * @param {any} value - 要验证的值
   * @returns {boolean} 是否为有效经验值
   */
  static isValidXP(value) {
    return this.isValidInteger(value, 0);
  }
}

/**
 * 数字格式化工具类
 * 提供各种数字格式化功能
 */
export class NumberUtils {
  /**
   * 格式化数字为千分位显示
   * @param {number} number - 要格式化的数字
   * @returns {string} 格式化后的字符串
   */
  static formatWithCommas(number) {
    if (!ValidationUtils.isValidNumber(number)) return '0';
    return Math.round(number).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  }

  /**
   * 格式化经验值显示
   * @param {number} xp - 经验值
   * @returns {string} 格式化后的经验值字符串
   */
  static formatXP(xp) {
    if (!ValidationUtils.isValidNumber(xp)) return '0 XP';
    if (xp >= 1000000) {
      return `${(xp / 1000000).toFixed(1)}M XP`;
    } else if (xp >= 1000) {
      return `${(xp / 1000).toFixed(1)}K XP`;
    }
    return `${Math.round(xp)} XP`;
  }

  /**
   * 格式化百分比显示
   * @param {number} value - 数值
   * @param {number} total - 总数
   * @param {number} decimals - 小数位数，默认0
   * @returns {string} 格式化后的百分比字符串
   */
  static formatPercentage(value, total, decimals = 0) {
    if (!ValidationUtils.isValidNumber(value) || !ValidationUtils.isValidNumber(total) || total === 0) {
      return '0%';
    }
    const percentage = (value / total) * 100;
    return `${percentage.toFixed(decimals)}%`;
  }

  /**
   * 格式化等级显示
   * @param {number} level - 等级
   * @returns {string} 格式化后的等级字符串
   */
  static formatLevel(level) {
    if (!ValidationUtils.isValidInteger(level, 1)) return '等级 1';
    return `等级 ${level}`;
  }

  /**
   * 格式化连续天数显示
   * @param {number} streak - 连续天数
   * @returns {string} 格式化后的连续天数字符串
   */
  static formatStreak(streak) {
    if (!ValidationUtils.isValidInteger(streak, 0)) return '0天';
    return `${streak}天`;
  }

  /**
   * 安全的数学运算
   * @param {number} a - 第一个数
   * @param {number} b - 第二个数
   * @param {string} operation - 运算类型：'add', 'subtract', 'multiply', 'divide'
   * @returns {number} 运算结果
   */
  static safeMath(a, b, operation) {
    if (!ValidationUtils.isValidNumber(a) || !ValidationUtils.isValidNumber(b)) {
      return 0;
    }
    
    switch (operation) {
      case 'add':
        return a + b;
      case 'subtract':
        return a - b;
      case 'multiply':
        return a * b;
      case 'divide':
        return b !== 0 ? a / b : 0;
      default:
        return 0;
    }
  }
}

/**
 * 日期时间工具类
 * 提供各种日期时间处理功能
 */
export class DateUtils {
  /**
   * 格式化日期为中文显示
   * @param {Date|string} date - 日期对象或日期字符串
   * @param {string} format - 格式类型：'full', 'date', 'time', 'relative'
   * @returns {string} 格式化后的日期字符串
   */
  static formatDate(date, format = 'date') {
    if (!date) return '';
    
    const dateObj = date instanceof Date ? date : new Date(date);
    if (isNaN(dateObj.getTime())) return '';

    const now = new Date();
    const year = dateObj.getFullYear();
    const month = dateObj.getMonth() + 1;
    const day = dateObj.getDate();
    const hour = dateObj.getHours();
    const minute = dateObj.getMinutes();

    switch (format) {
      case 'full':
        return `${year}年${month}月${day}日 ${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
      case 'date':
        return `${year}年${month}月${day}日`;
      case 'time':
        return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
      case 'relative':
        return this.getRelativeTime(dateObj, now);
      default:
        return `${year}年${month}月${day}日`;
    }
  }

  /**
   * 获取相对时间描述
   * @param {Date} date - 目标日期
   * @param {Date} now - 当前日期
   * @returns {string} 相对时间描述
   */
  static getRelativeTime(date, now = new Date()) {
    const diffMs = now.getTime() - date.getTime();
    const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
    
    if (diffDays === 0) {
      const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
      if (diffHours === 0) {
        const diffMinutes = Math.floor(diffMs / (1000 * 60));
        return diffMinutes <= 0 ? '刚刚' : `${diffMinutes}分钟前`;
      }
      return `${diffHours}小时前`;
    } else if (diffDays === 1) {
      return '昨天';
    } else if (diffDays === 2) {
      return '前天';
    } else if (diffDays <= 7) {
      return `${diffDays}天前`;
    } else {
      return this.formatDate(date, 'date');
    }
  }

  /**
   * 检查是否为今天
   * @param {Date|string} date - 要检查的日期
   * @returns {boolean} 是否为今天
   */
  static isToday(date) {
    if (!date) return false;
    const dateObj = date instanceof Date ? date : new Date(date);
    const today = new Date();
    return dateObj.toDateString() === today.toDateString();
  }

  /**
   * 检查是否为昨天
   * @param {Date|string} date - 要检查的日期
   * @returns {boolean} 是否为昨天
   */
  static isYesterday(date) {
    if (!date) return false;
    const dateObj = date instanceof Date ? date : new Date(date);
    const yesterday = new Date();
    yesterday.setDate(yesterday.getDate() - 1);
    return dateObj.toDateString() === yesterday.toDateString();
  }

  /**
   * 获取日期差（天数）
   * @param {Date|string} date1 - 第一个日期
   * @param {Date|string} date2 - 第二个日期
   * @returns {number} 相差天数
   */
  static getDaysDifference(date1, date2) {
    const d1 = date1 instanceof Date ? date1 : new Date(date1);
    const d2 = date2 instanceof Date ? date2 : new Date(date2);
    const diffTime = Math.abs(d2.getTime() - d1.getTime());
    return Math.floor(diffTime / (1000 * 60 * 60 * 24));
  }

  /**
   * 格式化学习时间（秒转换为分钟和秒）
   * @param {number} seconds - 秒数
   * @returns {string} 格式化后的时间字符串
   */
  static formatStudyTime(seconds) {
    if (!ValidationUtils.isValidNumber(seconds) || seconds < 0) return '0秒';
    
    const minutes = Math.floor(seconds / 60);
    const remainingSeconds = seconds % 60;
    
    if (minutes === 0) {
      return `${remainingSeconds}秒`;
    } else if (remainingSeconds === 0) {
      return `${minutes}分钟`;
    } else {
      return `${minutes}分${remainingSeconds}秒`;
    }
  }
}

/**
 * 字符串处理工具类
 * 提供各种字符串处理功能
 */
export class StringUtils {
  /**
   * 安全的字符串截取
   * @param {string} str - 原字符串
   * @param {number} maxLength - 最大长度
   * @param {string} suffix - 后缀，默认为'...'
   * @returns {string} 截取后的字符串
   */
  static truncate(str, maxLength, suffix = '...') {
    if (!str || typeof str !== 'string') return '';
    if (str.length <= maxLength) return str;
    return str.substring(0, maxLength - suffix.length) + suffix;
  }

  /**
   * 首字母大写
   * @param {string} str - 原字符串
   * @returns {string} 首字母大写的字符串
   */
  static capitalize(str) {
    if (!str || typeof str !== 'string') return '';
    return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
  }

  /**
   * 移除HTML标签
   * @param {string} str - 包含HTML的字符串
   * @returns {string} 移除HTML标签后的字符串
   */
  static stripHtml(str) {
    if (!str || typeof str !== 'string') return '';
    return str.replace(/<[^>]*>/g, '');
  }

  /**
   * 生成随机字符串
   * @param {number} length - 字符串长度
   * @param {string} characters - 可用字符集
   * @returns {string} 随机字符串
   */
  static generateRandomString(length = 8, characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
    let result = '';
    for (let i = 0; i < length; i++) {
      result += characters.charAt(Math.floor(Math.random() * characters.length));
    }
    return result;
  }

  /**
   * 检查字符串是否包含中文字符
   * @param {string} str - 要检查的字符串
   * @returns {boolean} 是否包含中文字符
   */
  static hasChinese(str) {
    if (!str || typeof str !== 'string') return false;
    return /[\u4e00-\u9fff]/.test(str);
  }

  /**
   * 检查字符串是否包含英文字符
   * @param {string} str - 要检查的字符串
   * @returns {boolean} 是否包含英文字符
   */
  static hasEnglish(str) {
    if (!str || typeof str !== 'string') return false;
    return /[a-zA-Z]/.test(str);
  }
}

/**
 * 数组处理工具类
 * 提供各种数组处理功能
 */
export class ArrayUtils {
  /**
   * 安全的数组随机打乱
   * @param {Array} array - 原数组
   * @returns {Array} 打乱后的新数组
   */
  static shuffle(array) {
    if (!Array.isArray(array)) return [];
    const newArray = [...array];
    for (let i = newArray.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [newArray[i], newArray[j]] = [newArray[j], newArray[i]];
    }
    return newArray;
  }

  /**
   * 安全的数组随机选择
   * @param {Array} array - 原数组
   * @param {number} count - 选择数量
   * @returns {Array} 随机选择的元素数组
   */
  static randomSelect(array, count = 1) {
    if (!Array.isArray(array) || array.length === 0) return [];
    if (count >= array.length) return this.shuffle(array);
    
    const shuffled = this.shuffle(array);
    return shuffled.slice(0, count);
  }

  /**
   * 数组去重
   * @param {Array} array - 原数组
   * @param {string} key - 对象数组时的去重键名
   * @returns {Array} 去重后的数组
   */
  static unique(array, key = null) {
    if (!Array.isArray(array)) return [];
    
    if (key) {
      // 对象数组去重
      const seen = new Set();
      return array.filter(item => {
        const value = item[key];
        if (seen.has(value)) {
          return false;
        }
        seen.add(value);
        return true;
      });
    } else {
      // 基本类型数组去重
      return [...new Set(array)];
    }
  }

  /**
   * 安全的数组分块
   * @param {Array} array - 原数组
   * @param {number} size - 每块大小
   * @returns {Array} 分块后的二维数组
   */
  static chunk(array, size) {
    if (!Array.isArray(array) || size <= 0) return [];
    const chunks = [];
    for (let i = 0; i < array.length; i += size) {
      chunks.push(array.slice(i, i + size));
    }
    return chunks;
  }
}

/**
 * 对象处理工具类
 * 提供各种对象处理功能
 */
export class ObjectUtils {
  /**
   * 深拷贝对象
   * @param {any} obj - 要拷贝的对象
   * @returns {any} 深拷贝后的对象
   */
  static deepClone(obj) {
    if (obj === null || typeof obj !== 'object') return obj;
    if (obj instanceof Date) return new Date(obj.getTime());
    if (obj instanceof Array) return obj.map(item => this.deepClone(item));
    if (typeof obj === 'object') {
      const clonedObj = {};
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          clonedObj[key] = this.deepClone(obj[key]);
        }
      }
      return clonedObj;
    }
    return obj;
  }

  /**
   * 安全的对象属性访问
   * @param {Object} obj - 目标对象
   * @param {string} path - 属性路径，如 'user.profile.name'
   * @param {any} defaultValue - 默认值
   * @returns {any} 属性值或默认值
   */
  static safeGet(obj, path, defaultValue = null) {
    if (!obj || typeof obj !== 'object' || !path) return defaultValue;
    
    const keys = path.split('.');
    let current = obj;
    
    for (const key of keys) {
      if (current === null || current === undefined || !(key in current)) {
        return defaultValue;
      }
      current = current[key];
    }
    
    return current;
  }

  /**
   * 对象合并（深度合并）
   * @param {Object} target - 目标对象
   * @param {...Object} sources - 源对象
   * @returns {Object} 合并后的对象
   */
  static deepMerge(target, ...sources) {
    if (!sources.length) return target;
    const source = sources.shift();

    if (this.isObject(target) && this.isObject(source)) {
      for (const key in source) {
        if (this.isObject(source[key])) {
          if (!target[key]) Object.assign(target, { [key]: {} });
          this.deepMerge(target[key], source[key]);
        } else {
          Object.assign(target, { [key]: source[key] });
        }
      }
    }

    return this.deepMerge(target, ...sources);
  }

  /**
   * 检查是否为对象
   * @param {any} item - 要检查的项
   * @returns {boolean} 是否为对象
   */
  static isObject(item) {
    return item && typeof item === 'object' && !Array.isArray(item);
  }
}

/**
 * 错误处理工具类
 * 提供统一的错误处理功能
 */
export class ErrorUtils {
  /**
   * 安全的错误日志记录
   * @param {string} context - 错误上下文
   * @param {Error|string} error - 错误对象或错误信息
   * @param {Object} additionalData - 附加数据
   */
  static logError(context, error, additionalData = {}) {
    const errorInfo = {
      context,
      message: error instanceof Error ? error.message : error,
      stack: error instanceof Error ? error.stack : null,
      timestamp: new Date().toISOString(),
      ...additionalData
    };
    
    console.error(`[${context}] 错误:`, errorInfo);
  }

  /**
   * 安全的警告日志记录
   * @param {string} context - 警告上下文
   * @param {string} message - 警告信息
   * @param {Object} additionalData - 附加数据
   */
  static logWarning(context, message, additionalData = {}) {
    const warningInfo = {
      context,
      message,
      timestamp: new Date().toISOString(),
      ...additionalData
    };
    
    console.warn(`[${context}] 警告:`, warningInfo);
  }

  /**
   * 创建标准化的错误对象
   * @param {string} message - 错误信息
   * @param {string} code - 错误代码
   * @param {any} details - 错误详情
   * @returns {Error} 标准化的错误对象
   */
  static createError(message, code = 'UNKNOWN_ERROR', details = null) {
    const error = new Error(message);
    error.code = code;
    error.details = details;
    error.timestamp = new Date().toISOString();
    return error;
  }
}

/**
 * 性能监控工具类
 * 提供性能监控和优化功能
 */
export class PerformanceUtils {
  static timers = new Map();

  /**
   * 开始计时
   * @param {string} label - 计时标签
   */
  static startTimer(label) {
    this.timers.set(label, Date.now());
  }

  /**
   * 结束计时并返回耗时
   * @param {string} label - 计时标签
   * @returns {number} 耗时（毫秒）
   */
  static endTimer(label) {
    const startTime = this.timers.get(label);
    if (!startTime) {
      console.warn(`计时器 "${label}" 不存在`);
      return 0;
    }
    
    const endTime = Date.now();
    const duration = endTime - startTime;
    this.timers.delete(label);
    
    console.log(`[性能监控] ${label}: ${duration}ms`);
    return duration;
  }

  /**
   * 防抖函数
   * @param {Function} func - 要防抖的函数
   * @param {number} delay - 延迟时间（毫秒）
   * @returns {Function} 防抖后的函数
   */
  static debounce(func, delay) {
    let timeoutId;
    return function (...args) {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => func.apply(this, args), delay);
    };
  }

  /**
   * 节流函数
   * @param {Function} func - 要节流的函数
   * @param {number} limit - 限制时间（毫秒）
   * @returns {Function} 节流后的函数
   */
  static throttle(func, limit) {
    let inThrottle;
    return function (...args) {
      if (!inThrottle) {
        func.apply(this, args);
        inThrottle = true;
        setTimeout(() => inThrottle = false, limit);
      }
    };
  }
}